package com.eshop.config.thread;

import org.springframework.stereotype.Component;

import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 这是一个自定义的线程工厂类 TheadFactoryName，它实现了 java.util.concurrent.ThreadFactory 接口，用于创建具有特定命名格式和属性的新线程。以下是该类的主要功能解释：
 *
 * 静态成员变量 POOL_NUMBER：一个原子整数，用于为每个线程池分配唯一的序号，确保创建的线程池名称具有唯一性。
 *
 * 构造函数：
 *
 * 默认构造函数接受一个线程池名称 "el-pool"，并调用私有构造函数进行初始化。
 * 私有构造函数接收一个名称参数，创建一个新的 ThreadGroup 对象（如果没有安全管理器则使用当前线程的线程组），初始化线程序号计数器（threadNumber），并设置线程名称前缀，该前缀由传入的名称加上全局唯一的 POOL_NUMBER 序号组成。
 * newThread(Runnable r) 方法：
 *
 * 覆写了 ThreadFactory 接口的 newThread 方法，用于创建新的线程实例。
 * 创建的线程属于指定的 group 线程组，并将给定的 Runnable 任务作为目标运行对象。
 * 线程的名字采用预设的格式：namePrefix + "-thread-" + threadNumber.getAndIncrement()，这样创建出来的线程名字带有统一的前缀和递增的数字标识。
 * 确保新创建的线程不是守护线程（如果默认是的话，就改为非守护线程）。
 * 设置线程优先级为5（如果不为5的话，强制设置为5）。
 * 静态初始化块：
 *
 * 初始化静态变量 POOL_NUMBER 为一个新的 AtomicInteger 对象，初始值为1。
 * 总结起来，这个 TheadFactoryName 类主要目的是为了创建一系列命名和属性一致的线程，常用于多线程编程中的线程池环境，方便管理和追踪各个线程的执行情况。
 */
@Component
public class TheadFactoryName implements ThreadFactory
{
    private static final AtomicInteger POOL_NUMBER;
    private final ThreadGroup group;
    private final AtomicInteger threadNumber;
    private final String namePrefix;
    
    public TheadFactoryName() {
        this("el-pool");
    }
    
    private TheadFactoryName(final String name) {
        this.threadNumber = new AtomicInteger(1);
        final SecurityManager s = System.getSecurityManager();
        this.group = ((s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup());
        this.namePrefix = name + TheadFactoryName.POOL_NUMBER.getAndIncrement();
    }
    
    @Override
    public Thread newThread(final Runnable r) {
        final Thread t = new Thread(this.group, r, this.namePrefix + "-thread-" + this.threadNumber.getAndIncrement(), 0L);
        if (t.isDaemon()) {
            t.setDaemon(false);
        }
        if (t.getPriority() != 5) {
            t.setPriority(5);
        }
        return t;
    }
    
    static {
        POOL_NUMBER = new AtomicInteger(1);
    }
}
